package com.example.rjb_shoping.auth;

import com.alibaba.fastjson.JSON;
import com.example.rjb_shoping.entity.RjbAdmin;
import com.example.rjb_shoping.entity.RjbRule;
import com.example.rjb_shoping.util.JwtUtils;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义认证过滤器，继承UsernamePasswordAuthenticationFilter
 * 验证用户名密码正确后 生成一个token并将token返回给客户端
 */
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    //认证管理器
    private AuthenticationManager authenticationManager;
    private RsaKeyProperties prop; //公钥、私钥属性对象
    public TokenLoginFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop) {
        this.authenticationManager = authenticationManager;
        this.prop = prop;
    }
    /**
     * 重写attemptAuthentication（）认证请求方法
     * @return
     * @throws AuthenticationException
     */
    public Authentication attemptAuthentication(HttpServletRequest request
            , HttpServletResponse response) throws AuthenticationException {
        try {
            //将数据转User对象
            RjbAdmin sysUser = JSON.parseObject(request.getInputStream(), RjbAdmin.class);
            System.out.println("username=" + sysUser.getUsername());
            System.out.println("pwd=" + sysUser.getPassword());
            //创建认证对象
            UsernamePasswordAuthenticationToken authRequest =
                    new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword());
            return authenticationManager.authenticate(authRequest);
        }catch (Exception e){
            try {
                response.setContentType("application/json;charset=utf-8");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);//设置401认证异常状态
                PrintWriter out = response.getWriter();
                Map resultMap = new HashMap();
                resultMap.put("code", HttpServletResponse.SC_UNAUTHORIZED);
                resultMap.put("msg", "用户名或密码错误！");
                out.write(JSON.toJSONString(resultMap)); //Map转JSON串
                out.flush();
                out.close();
            }catch (Exception outEx){
                outEx.printStackTrace();
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * 认证成功后处理把用户信息生成一个token, 并将token返回给客户端
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response
            , FilterChain chain, Authentication authResult) throws IOException, ServletException {
        RjbAdmin user = new RjbAdmin();
        user.setUsername(authResult.getName());
        //将权限集合放入用户对象中
        user.setRoles((List<RjbRule>)authResult.getAuthorities());
        //生成JWT Token串， 有效期：24 * 60分钟 = 24小时
        String token = JwtUtils.generateTokenExpireInMinutes(user, prop.getPrivateKey(), 24 * 60);
        //将token写入response的header中
        response.addHeader("Authorization", "Bearer "+token);
        //CORS跨域时，通过此header设置暴露Authorization允许前端访问
        response.addHeader("Access-Control-Expose-Headers", "Authorization");
        try {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);//HttpServletResponse.SC_OK 200状态
            PrintWriter out = response.getWriter();
            Map resultMap = new HashMap();
            resultMap.put("code", HttpServletResponse.SC_OK);
            resultMap.put("msg", "认证通过！");
            out.write(JSON.toJSONString(resultMap)); //Map转JSON串
            out.flush();
            out.close();
        }catch (Exception outEx){
            outEx.printStackTrace();
        }
    }

    /**
     * 验证【失败】调用的方法
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                              AuthenticationException failed) throws IOException, ServletException {
        String returnData="";
        // 账号过期
        if (failed instanceof AccountExpiredException) {
            returnData="账号过期";
        }
        // 密码错误
        else if (failed instanceof BadCredentialsException) {
            returnData="密码错误";
        }
        // 密码过期
        else if (failed instanceof CredentialsExpiredException) {
            returnData="密码过期";
        }
        // 账号不可用
        else if (failed instanceof DisabledException) {
            returnData="账号不可用";
        }
        //账号锁定
        else if (failed instanceof LockedException) {
            returnData="账号锁定";
        }
        // 用户不存在
        else if (failed instanceof InternalAuthenticationServiceException) {
            returnData="用户不存在";
        }
        // 其他错误
        else{
            returnData="未知异常";
        }

        // 处理编码方式 防止中文乱码
        response.setContentType("text/json;charset=utf-8");
        // 将反馈塞到HttpServletResponse中返回给前台
        response.getWriter().write(JSON.toJSONString(returnData));
    }
}
